//
// Controller connection
//

#ifndef _CON_CONNECTION_H_
#define _CON_CONNECTION_H_

#include <boost/function.hpp>
#include <boost/asio.hpp>
#include <boost/array.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/thread.hpp>
#include <list>

#include "sqlhandle.h"
#include "teacup.h"

class controllers_network;
class con_command;
class controllers_network;

class con_connection: public boost::enable_shared_from_this<con_connection>,
		private boost::noncopyable
{
	public:

		explicit con_connection(boost::asio::io_service &_io_service,
				controllers_network &_network, sqlhandle &_sqlhandle);

		~con_connection();

		boost::asio::ip::tcp::socket& socket();

		void start();

		boost::asio::ip::address remote_address();

		void add_command_to_queue(con_command *_command);

		bool pult_connection_;
		unsigned int controller_id_;

		con_state state_;

		teacup encoder_;
		bool secure_connection_;
		bool need_remove_controller_;

		void close_connection();

	protected:

		void controller_handle_read(const boost::system::error_code& _error,
				size_t _bytes_transferred);
		void controller_handle_write(const boost::system::error_code& _error);
		void controller_handle_last_write(
				const boost::system::error_code& _error);
		void controller_handle_timer(const boost::system::error_code &_error);
		void controller_handle_read_timeout(
				const boost::system::error_code &_error);

		int read_restart_count_;

		void start_read_timeout();

		void start_new_command(con_command *_command);
		bool start_command_from_queue();
		void start_queue_command();

		void start_command();
		void start_timer();

		boost::asio::deadline_timer timer_;

		void dump_packet(bool _read, boost::asio::const_buffer _buffer,
				unsigned int _size = 0);

		boost::asio::ip::tcp::socket socket_;
		boost::asio::io_service::strand strand_;
		con_command *command_;

		enum
		{
			buffer_len_ = 1024
		}; // buffer for read from controller

		boost::array<char, buffer_len_> read_buffer_;
		std::vector<boost::asio::const_buffer> write_buffer_;

		controllers_network &network_;
		sqlhandle &sqlhandle_;

		typedef std::list<con_command*> command_queue_t;

		command_queue_t command_queue_;
		boost::mutex command_queue_mutex_;

};

typedef boost::shared_ptr<con_connection> con_connection_ptr;

#endif // _CON_CONNECTION_H_
